﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 双色球
{
    /// <summary>
    /// 多线程双色球项目:
    /// 双色球：投注号码由6个红色球号码和1个蓝色球号码组成。
    /// 红色球号码从01--33中选择（不重复）
    /// 蓝色球号码从01--16中选择（可以跟红球重复）
    /// 7个球杂乱无章的变化：球的号码来自于复杂数据计算，
    ///                      可能需要纳斯达克股票指数+全球气象指数+。。。（费时间）
    /// 
    /// 随机的规则是远程获取一个数据的，这个会有较长的时间损耗
    /// 多线程
    /// </summary>
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.button1.Enabled = true;
            this.button2.Enabled = false;
        }

        /// <summary>
        /// 红球集合
        /// </summary>
        private string[] RedNums =
        {
            "01","02","03","04","05","06","07","08","09","10",
            "11","12","13","14","15","16","17","18","19","20",
            "21","22","23","24","25","26","27","28","29","30",
            "31","32","33"
        };

        /// <summary>
        /// 蓝球集合
        /// </summary>
        private string[] BlueNums =
        {
            "01","02","03","04","05","06","07","08","09","10",
            "11","12","13","14","15","16"
        };

        //对象锁
        private readonly object obj = new object();
        //创建一个公共变量
        private bool IsSotp = true;

        /// <summary>
        /// 开始
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //初始化
            this.button1.Text = "运行中";
            this.button1.Enabled = false;
            IsSotp = true;


            //创建一个线程工厂
            TaskFactory taskFactory = new TaskFactory();
            //首先我们这里是6个球同时进行变动，所以要创建6个线程
            List<Task> tasks = new List<Task>();
            foreach (var controls in this.groupBox1.Controls)
            {
                //获取其中的标签控件
                if (controls is Label)
                {
                    //转换成Label
                    Label label = (Label)controls;
                    //区分红球和蓝球，因为蓝球可以随便动
                    if (label.Name == "label6")
                    {
                        tasks.Add(taskFactory.StartNew(() =>
                        {
                            //判断是否需要停止
                            while (IsSotp)
                            {
                                Thread.Sleep(new Random().Next(500, 1000));//随机休息一下
                                this.UpdateLbl(label, BlueNums[new Random().Next(0, 16)]);
                            }
                        }));
                    }
                    //红球的特点不能出现重复的数组
                    else
                    {
                        tasks.Add(taskFactory.StartNew(() =>
                        {
                            while (IsSotp)
                            {
                                Thread.Sleep(new Random().Next(500, 1000));//随机休息一下
                                string str = RedNums[new Random().Next(0, 33)];
                                //锁住判断是否重复的判断，和更新UI代码
                                lock (obj)
                                {
                                    if (IsNum(str))
                                    {
                                        continue;
                                    }
                                    this.UpdateLbl(label, str);
                                }
                            }
                        }));
                    }
                }
            }

            //当我们所有的数不为00就可以显示暂停了所以要在开启一个线程
            taskFactory.StartNew(() =>
            {
                while (true)
                {
                    Thread.Sleep(500);
                    if (!this.IsNum("00") && this.label6.Text != "00")
                    {
                        //修改停止的状态
                        this.Invoke(new Action(() =>
                        {
                            this.button2.Enabled = true;
                        }));
                        break;
                    }
                }
            });

            //停止回调函数
            taskFactory.ContinueWhenAll(tasks.ToArray(), x => ShowResult());
        }

        /// <summary>
        /// 结束
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            IsSotp = false;
            this.button1.Enabled = true;
            this.button1.Text = "开始";
            this.button2.Enabled = false;
        }


        /// <summary>
        /// 弹框提示数据
        /// </summary>
        private void ShowResult()
        {
            MessageBox.Show(string.Format("本期双色球结果为：{0} {1} {2} {3} {4} 蓝球{5}"
                , this.label1.Text
                , this.label2.Text
                , this.label3.Text
                , this.label4.Text
                , this.label5.Text
                , this.label6.Text));
        }

        /// <summary>
        /// 判断是不是存在这个值
        /// </summary>
        /// <param name="num"></param>
        public bool IsNum(string num)
        {
            //遍历所有的Label值
            foreach (var controls in this.groupBox1.Controls)
            {
                if (controls is Label)
                {
                    Label label = (Label)controls;
                    if (label.Name != "label6" && label.Text == num)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        #region PrivateMethod
        /// <summary>
        /// 更新界面
        /// </summary>
        /// <param name="lbl"></param>
        /// <param name="text"></param>
        private void UpdateLbl(Label lbl, string text)
        {
            if (lbl.InvokeRequired)//启动form时候 去设置一个非线程安全的属性
            {
                this.Invoke(new Action(() =>
                {
                    //if (IsSotp)//不延迟，点了停止，就不会再更新,放弃了最后那次更新
                    {
                        lbl.Text = text;
                        //Thread.Sleep(2000);
                        Console.WriteLine($"当前UpdateLbl线程id{Thread.CurrentThread.ManagedThreadId}");
                    }
                }));//交给UI线程去更新
            }
            else
            {
                lbl.Text = text;
            }
        }
        #endregion
    }
}
